package ide.ccf.ccproject.dialogs;

import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;
import java.io.BufferedReader;
import java.io.InputStreamReader;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.editors.text.TextEditor;
import org.eclipse.ui.PartInitException;
import org.eclipse.jface.text.IDocument;

import ide.ccf.ccproject.common.ProjectVisitor;
import ide.ccf.ccproject.editors.ProjectFileEditor;
import ide.ccf.ccproject.pages.embedded.ScopeList;

/**
 * 选择作用域对话框
 *
 */
@SuppressWarnings("rawtypes")
public class SelectScopeDialog extends Dialog implements SelectionListener 
{
	private ScopeList m_scope;
	private Label m_label;
	private Combo m_combo;
	
	private IProject m_pro;
	private Map m_files;
	private Vector m_profiles;
	private String m_desc = "";
	private boolean m_remove = false;
	
	/**
	 * 构造器
	 * @param parentShell
	 * @param pro
	 */
	public SelectScopeDialog(Shell parentShell, IProject pro) 
	{
		super(parentShell);
		
		m_pro = pro;
		m_profiles = new Vector();
		m_files = new HashMap();
	}
	
	/**
	 * 设置对话框描述信息
	 * @param desc
	 */
	public void setDescription(String desc) 
	{
		m_desc = desc;
	}
    
	/**
	 * 添加文件
	 * @param files
	 * @param var
	 */
    @SuppressWarnings("unchecked")
	public void addFiles(Vector files, String var) 
    {
		m_remove = false;
		
		if (!m_desc.equals(""))
			m_desc = "选择文件要插入的项目设置:";											
				
		m_files.put(var, files);
	}

	@SuppressWarnings("unchecked")
	public void removeFiles(Vector files, String var) 
	{
    	m_remove = true;
    	
		if (!m_desc.equals(""))
			m_desc = "文件将会从下列项目设置中删除:";											
    	
		m_files.put(var, files);
    }
    
	/**
	 * 控件选择改变事件
	 */
    public void widgetSelected(SelectionEvent e) 
    {
		int index = m_combo.getSelectionIndex();
		
		setProjectFile((IFile)m_profiles.get(index));
	}
	
    /**
     * 控件默认选择
     */
	public void widgetDefaultSelected(SelectionEvent e) 
	{
		
	}
	
	/**
	 * 确定按钮单击事件
	 */
	public void okPressed() 
	{
		for (int i = 0; i < m_profiles.size(); ++i) 
		{
			IFile file = (IFile)m_profiles.get(i);
			String proFileName = file.getLocation().toOSString();
			
			if (!m_scope.isChanged(proFileName))
				continue;

			String contents;
			
	    	if (m_remove)
				contents = m_scope.removeFiles(proFileName);
			else
				contents = m_scope.addFiles(proFileName);
				
			openAndModifyProjectFile(file, contents);
 		}
		close();
	}
	
	/**
	 * 取消按钮单击事件
	 */
	public void cancelPressed() 
	{
		close();
	}

	/**
	 * 设置项目文件
	 * @param file
	 */
	protected void setProjectFile(IFile file) 
	{
		m_scope.showModel(file.getLocation().toOSString(), getProjectFileContents(file), !m_remove);
	}
	
	/**
	 * 获取文件内容
	 * @param file
	 * @return
	 */
	private String getProjectFileContents(IFile file) 
	{
		IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
		IEditorPart part = page.findEditor(new FileEditorInput(file));
		String contents = new String();
		
		if (part instanceof ProjectFileEditor) 
		{
			/*TextEditor te = (TextEditor)part;
			IDocumentProvider provider = te.getDocumentProvider();
			IDocument document = provider.getDocument(te.getEditorInput());
			contents = document.get();*/
			contents = ((ProjectFileEditor) part).getVisualEditor().contents();
		}
		else 
		{
			try 
			{
				BufferedReader reader = new BufferedReader(new InputStreamReader(file.getContents()));
				String line;
				
				do 
				{
					line = reader.readLine();
					
					if (line != null)
						contents += line + "\n";
				} while (line != null);
				
				reader.close();
			} 
			catch (Exception e) 
			{
			}
		}
        return contents;		
	}
	
	/**
	 * 打开并编辑项目文件
	 * @param file
	 * @param newContents
	 */
	protected void openAndModifyProjectFile(IFile file, String newContents) 
	{
		try 
		{
			IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
			IEditorPart part = page.openEditor(new FileEditorInput(file), ProjectFileEditor.ID, true, IWorkbenchPage.MATCH_ID | IWorkbenchPage.MATCH_INPUT);
			
			if (part instanceof ProjectFileEditor) 
			{
				// TODO 要同步可视化编辑器和源码编辑器，这几条代码应该有BUG，比如项目文件在之前就被修改掉了，数据会不会丢失？目前先这样了。
				/*TextEditor te = (TextEditor)part;
				IDocumentProvider provider = te.getDocumentProvider();
				IDocument document = provider.getDocument(te.getEditorInput());
				document.set(newContents);*/

				((ProjectFileEditor) part).getSourceEditor().getDocument().set(newContents);
				((ProjectFileEditor) part).getSourceEditor().doSave(new NullProgressMonitor());
				((ProjectFileEditor) part).reload();
			}
		} 
		catch (WorkbenchException e) 
		{
			e.printStackTrace();
		}
	}
	
	/**
	 * 查找项目文件
	 * @return
	 */
	@SuppressWarnings("unchecked")
	protected boolean findProjectFiles() 
	{
		ProjectVisitor provisitor = new ProjectVisitor();
		m_profiles.addAll(provisitor.findFiles(m_pro, "pro"));
		m_profiles.addAll(provisitor.findFiles(m_pro, "pri"));
		
		Collections.sort(m_profiles, new Comparator() 
		{
			public int compare(Object o1, Object o2) 
			{
				int res = ((IResource)o1).getParent().getProjectRelativePath().toOSString().compareTo(((IResource)o2).getParent().getProjectRelativePath().toOSString());
				
				if (res != 0)
					return res;
				
				return ((IResource)o1).getName().compareTo(((IResource)o2).getName());
			}
			
			public boolean equals(Object obj) 
			{ 
				return compare(this, obj) == 0; 
			}
		});
		return !m_profiles.isEmpty();
	}
	
	/**
	 * 添加文件
	 */
	protected void addFiles() 
	{
		Iterator keyit = m_files.keySet().iterator();
		
		while (keyit.hasNext()) 
		{
			String var = (String)keyit.next();
			Vector files = (Vector)m_files.get(var);
			
			for (int i = 0; i < files.size(); ++i) 
			{
				m_scope.addFile(((IFile)files.get(i)).getLocation().toOSString(), var);
			}
		}
	}
	
	/**
	 * 创建删除文件对话框
	 * @param composite
	 */
	@SuppressWarnings("unchecked")
	protected void createRemoveDialog(Composite composite) 
	{
		m_combo = new Combo(composite, SWT.READ_ONLY);
		
		GridData data = new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL);
        data.widthHint = convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH);
        m_combo.setLayoutData(data);
        m_combo.setFont(composite.getParent().getFont());
		
		m_scope = new ScopeList(composite, SWT.EMBEDDED);
        data = new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL);
        data.widthHint = convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH);
        data.heightHint = 300;
        m_scope.setLayoutData(data);
        m_scope.setFont(composite.getParent().getFont());

        addFiles();

		Vector profiles = m_profiles;
		m_profiles = new Vector();
		
		for (int i = 0; i < profiles.size(); ++i) 
		{
			IFile file = (IFile)profiles.get(i);
			
			if (m_scope.search(file.getLocation().toOSString(), getProjectFileContents(file))) 
			{
				m_profiles.add(file);
				m_combo.add(file.getProjectRelativePath().toOSString());
			}
		}
		
		if (!m_profiles.isEmpty()) 
		{
			selectProperProFile();
		} 
		else 
		{
			m_label.setText("无法在CCF项目文件中找到删除的文件。请手动编辑项目文件。");
			m_combo.setEnabled(false);
			m_scope.showModel("", "", false);
		}
	}
	
	/**
	 * 创建添加文件对话框
	 * @param composite
	 */
	protected void createAddDialog(Composite composite) 
	{		
		m_combo = new Combo(composite, SWT.READ_ONLY);
		
		for (int i = 0; i < m_profiles.size(); ++i) 
		{
			IResource res = (IResource)m_profiles.get(i);
			
			if (res.getType() == IResource.FILE) 
			{
				IFile f = (IFile)res;
				m_combo.add(f.getProjectRelativePath().toOSString());
			}
		}
		
		GridData data = new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL);
        data.widthHint = convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH);
        m_combo.setLayoutData(data);
        m_combo.setFont(composite.getParent().getFont());
        
		// 作用域选择树
        m_scope = new ScopeList(composite, SWT.EMBEDDED);
        data = new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL);
        data.widthHint = convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH);
        data.heightHint = 300;
        
        m_scope.setLayoutData(data);
        m_scope.setFont(composite.getParent().getFont());
        
        addFiles();

        if (!m_profiles.isEmpty()) 
        {
        	selectProperProFile();
			m_scope.selectFirstVariable();
        } 
        else 
        {
			m_label.setText("无法找到CCF项目文件。请手动编辑项目文件。");
			m_combo.setEnabled(false);
			m_scope.showModel("", "", false);
        }
	}

	/**
	 * 选择正确的项目文件
	 */
	private void selectProperProFile() 
	{
		int index = 0;
		if (!m_files.values().isEmpty()) 
		{
			IFile first = (IFile)((Vector)m_files.values().toArray()[0]).firstElement();
			String path = first.getParent().getProjectRelativePath().toPortableString();
			
			for (int i = 0; i < m_profiles.size(); i++) 
			{
				IPath otherPath = ((IResource)m_profiles.elementAt(i)).getParent().getProjectRelativePath();
				
				if (otherPath.toPortableString().equals(path)) 
				{
					index = i;
					
					if ("pro".equals(otherPath.getFileExtension()))
						break;
				}
			}
		}
		m_combo.select(index);
		m_combo.addSelectionListener(this);
		setProjectFile((IFile)m_profiles.get(index));
	}
	
	/**
	 * 创建按钮之上的对话框区域
	 */
	protected Control createDialogArea(Composite parent) 
	{
		Composite composite = (Composite) super.createDialogArea(parent);
		
		m_label = new Label(composite, SWT.WRAP);
		m_label.setText(m_desc);
		
        GridData data = new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL);
        data.widthHint = convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH);
        m_label.setLayoutData(data);
        m_label.setFont(composite.getParent().getFont());
		
        findProjectFiles();
        
		if (m_remove) 
		{
			createRemoveDialog(composite);
		} 
		else 
		{
			createAddDialog(composite);
		}

		applyDialogFont(composite);
		return composite;
	}
	
	/**
	 * 配置对话框标题
	 */
    protected void configureShell(Shell shell) 
    {
        super.configureShell(shell);
        
        if (m_remove)
        	shell.setText("从CCF项目删除文件");
        else
        	shell.setText("添加文件到CCF项目");
    }
}